package com.lvtulife.paas.gtd.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.lvtulife.common.bean.DelVo;
import com.lvtulife.common.component.constants.Constant;
import com.lvtulife.common.component.constants.ConstantUtil;
import com.lvtulife.common.component.exception.ErrMsg;
import com.lvtulife.common.service.impl.BaseServiceImpl;
import com.lvtulife.paas.gtd.bean.IdealVo;
import com.lvtulife.paas.gtd.entity.GtdIdeal;
import com.lvtulife.paas.gtd.mapper.GtdIdealMapper;
import com.lvtulife.paas.gtd.service.GtdIdealOplogServiceI;
import com.lvtulife.paas.gtd.service.GtdIdealServiceI;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.*;

/**
 * GtdIdeal 表数据服务层接口实现类
 */
@Service
@Transactional(readOnly = true)
public class GtdIdealServiceImpl extends BaseServiceImpl<GtdIdealMapper, GtdIdeal> implements GtdIdealServiceI {

    @Autowired
    private GtdIdealOplogServiceI oplogService;

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public Long saveIdeal(IdealVo vo) {
        GtdIdeal entity = initBean(vo);

        int count = 0;
        if (vo.getId() != null) {
            count = baseMapper.updateSelectiveById(entity);
            oplogService.saveOplog(entity.getId(), MessageFormat.format("{0},已更新", entity.getIdeal()));
        } else {
            count = baseMapper.insert(entity);
            oplogService.saveOplog(entity.getId(), MessageFormat.format("{0},已创建", entity.getIdeal()));
        }
        checkOperation(count);

        return entity.getId();
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void changeStatus(Long id, Integer status) {
        GtdIdeal entity = getEntity(id);

        /* 状态一致 */
        if (entity.getGiStatus().equals(status)) {
            return;
        }

        String opKey = "Gtd.IdealState.";
        switch (status) {
            case Constant.Gtd.IdealState.WAIT:
                changeWait(entity, status);
                opKey += "WAIT";
                break;
            case Constant.Gtd.IdealState.COMPLETED:
                changeCompleted(entity, status);
                opKey += "COMPLETED";
                break;
            case Constant.Gtd.IdealState.CANCEL:
                changeCancel(entity, status);
                opKey += "CANCEL";
                break;
            default:
                //等同 verifyConstant("Gtd.IdealState", status);
                throw new RuntimeException(ErrMsg.INVALID_CONTENT.getMsg());
        }

        /* 更新状态 */
        entity = new GtdIdeal(entity.getId());
        entity.setGiStatus(status);
        updateSelectiveEntity(entity);

        oplogService.saveOplog(entity.getId(), MessageFormat.format("状态更新为 {0} 状态", ConstantUtil.getInstance().getChildConstantLabel(opKey)));
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void topIdeal(Long id) {
        GtdIdeal entity = getEntity(id);
        int top = entity.getTop().equals(Constant.Gtd.Top.YES) ? Constant.Gtd.Top.NO : Constant.Gtd.Top.YES;

        entity = new GtdIdeal(id);
        entity.setTop(top);
        updateSelectiveEntity(entity);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void delIdeal(DelVo delVo) {
        verifyParams(delVo);
        delEntity(delVo.getId(), delVo.getUserId());
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void multiDelIdeal(DelVo delVo) {
        verifyParams(delVo);

        for (Long id : delVo.getIds()) {
            delEntity(id, delVo.getUserId());
        }
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void clearIdeal(Long userId) {
        verifyParams(userId);

        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("del", Constant.Base.State.DEL);
        baseMapper.clearUserIdeal(map);
    }

    @Override
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void sortIdeal(Long id, Integer sort) {
        /* 校验参数与操作对象 */
        GtdIdeal entity = verifyEntity(new GtdIdeal(id));

        /* 设置更新内容 */
        entity.setSort(sort == null || sort <= 0 ? 1 : sort);
        updateSelectiveEntity(entity);
    }

    @Override
    public Page<GtdIdeal> findIdealVos(Long userId, Page<GtdIdeal> query) {
        return selectPage(query, getDefaultWrapper(userId));
    }

    @Override
    public List<GtdIdeal> findIdeals(Long userId) {
        return selectList(getDefaultWrapper(userId));
    }

    @Override
    public List<IdealVo> findIdealVos(Long userId) {
        return convertList(findIdeals(userId));
    }


    @Override
    public List<IdealVo> findStatusIdeals(Long userId, Integer status) {
        /* 验证参数合法性 */
        verifyConstant("Gtd.IdealState", status);

        /* 设置查询参数 */
        EntityWrapper<GtdIdeal> wrapper = getDefaultWrapper(userId);
        wrapper.where("giStatus={0}", status);

        /* 按条件查询数据 */
        return convertList(selectList(wrapper));
    }

    @Override
    public List<IdealVo> findStrategyIdeals(Long userId, Long strategyId) {
        /* 设置查询参数 */
        EntityWrapper<GtdIdeal> wrapper = getDefaultWrapper(userId);
        wrapper.where("sid={0}", strategyId);

        /* 按条件查询数据 */
        return convertList(selectList(wrapper));
    }

    @Override
    public List<IdealVo> findLikeIdeals(Long userId, String likeStr) {
        /* 设置查询参数 */
        EntityWrapper<GtdIdeal> wrapper = getDefaultWrapper(userId);
        wrapper.like("ideal", likeStr);

         /* 按条件查询数据 */
        return convertList(selectList(wrapper));
    }


    private GtdIdeal initBean(IdealVo vo) {
        verifyParams(vo);

        GtdIdeal entity = null;
        if (vo.getId() != null) {
            entity = verifyEntity(new GtdIdeal(vo.getId()));

            /* 可修改项 */
            if (!StringUtils.isBlank(vo.getCode()))
                entity.setGiCode(vo.getCode());
            if (!StringUtils.isBlank(vo.getIdeal()))
                entity.setIdeal(vo.getIdeal());
            if (!StringUtils.isBlank(vo.getDetail()))
                entity.setDetail(vo.getDetail());
            if (!StringUtils.isBlank(vo.getCause()))
                entity.setCause(vo.getCause());
            if (vo.getHopeDt() != null)
                entity.setHopeDt(vo.getHopeDt());

            entity.setUpdatedDt(new Date());
        } else {
            verifyParams(vo.getUserId(), vo.getIdeal(), vo.getDetail(), vo.getCause(), vo.getCode(), vo.getHopeDt());

            entity = new GtdIdeal();
            if (vo.getTop() != null)
                entity.setTop(vo.getTop() ? Constant.Gtd.Top.YES : Constant.Gtd.Top.NO);
            else
                entity.setTop(Constant.Gtd.Top.NO);

            entity.setSort(1);
            entity.setGiStatus(Constant.Gtd.IdealState.WAIT);
            entity.setCreatedDt(new Date());
            entity.setUpdatedDt(entity.getCreatedDt());
            entity.setDel(Constant.Base.State.NORMAL);
            entity.setSid(0L);

            /* 必填项 */
            entity.setUid(vo.getUserId());
            entity.setGiCode(vo.getCode());
            entity.setIdeal(vo.getIdeal());
            entity.setDetail(vo.getDetail());
            entity.setCause(vo.getCause());
            entity.setHopeDt(vo.getHopeDt());
        }

        return entity;
    }

    /* 设置未达成状态 */
    private void changeWait(GtdIdeal entity, Integer status) {
        entity.setFinishDt(null);
    }

    /* 设置已达成状态 */
    private void changeCompleted(GtdIdeal entity, Integer status) {
        if (entity.getGiStatus().equals(Constant.Gtd.IdealState.CANCEL)) throw new RuntimeException("当前信息为作废状态,不允许更改成已达成状态");

        entity.setFinishDt(new Date());//完成时间
    }

    /* 设置作废状态 */
    private void changeCancel(GtdIdeal entity, Integer status) {
        if (entity.getGiStatus().equals(Constant.Gtd.IdealState.COMPLETED)) throw new RuntimeException("当前信息为已达成状态,不允许作废");

        entity.setFinishDt(new Date());//作废时间
    }

    /* 设置查询参数 */
    private EntityWrapper<GtdIdeal> getDefaultWrapper(Long userId) {
        verifyParams(userId);

        EntityWrapper<GtdIdeal> wrapper = new EntityWrapper<>();
        wrapper.where("uid={0} and del={1}", userId, Constant.Base.State.NORMAL);
        wrapper.orderBy("top DESC,sort ASC");
        return wrapper;
    }

    private List<IdealVo> convertList(List<GtdIdeal> list) {
        List<IdealVo> result = new ArrayList<>();
        for (GtdIdeal entity : list) {
            IdealVo vo = convertBeanToVo(entity);
            result.add(vo);
        }
        return result;
    }

    private IdealVo convertBeanToVo(GtdIdeal entity) {
        IdealVo vo = new IdealVo();
        vo.setId(entity.getId());
        vo.setUserId(entity.getUid());
        vo.setStrategyId(entity.getSid());
        vo.setIdeal(entity.getIdeal());
        vo.setDetail(entity.getDetail());
        vo.setCause(entity.getCause());
        vo.setCode(entity.getGiCode());
        vo.setStatus(entity.getGiStatus());
        vo.setSort(entity.getSort());
        if (entity.getTop() == null) {
            entity.setTop(Constant.Gtd.Top.NO);
        }
        vo.setTop(Constant.Gtd.Top.YES == entity.getTop().intValue());
        vo.setHopeDt(entity.getHopeDt());
        vo.setFinishDt(entity.getFinishDt());
        return vo;
    }

    private void delEntity(Long id, Long userId) {
        verifyParams(id, userId);

        GtdIdeal entity = getEntity(id);

        if (!entity.getUid().equals(userId)) {
            throw new RuntimeException(ErrMsg.PERMISSION_DENIED.getMsg());
        }

        delEntity(id);
    }

    private void delEntity(Long id) {
        GtdIdeal entity = new GtdIdeal(id);
        entity.setDel(Constant.Base.State.DEL);
        updateSelectiveEntity(entity);

        oplogService.saveOplog(id, "内容已删除");
    }

    /* 使用此方法必须在调用方加上事务处理注解 */
    private void updateEntity(GtdIdeal entity) {
        entity.setUpdatedDt(new Date());
        checkOperation(updateById(entity));
    }

    /* 使用此方法必须在调用方加上事务处理注解 */
    private void updateSelectiveEntity(GtdIdeal entity) {
        entity.setUpdatedDt(new Date());
        checkOperation(updateSelectiveById(entity));
    }
}